import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class CodeLineCounter {
    // 定义支持的编程语言及其文件扩展名和注释规则
    private static final Map<String, Language> SUPPORTED_LANGUAGES = new HashMap<>();

    static {
        SUPPORTED_LANGUAGES.put("java", new Language("java", new String[]{".java"}, "//", "/\\*", "\\*/"));
//        SUPPORTED_LANGUAGES.put("python", new Language("python", new String[]{".py"}, "#", null, null));
        SUPPORTED_LANGUAGES.put("cpp", new Language("cpp", new String[]{".cpp", ".h"}, "//", "/\\*", "\\*/"));
//        SUPPORTED_LANGUAGES.put("javascript", new Language("javascript", new String[]{".js"}, "//", "/\\*", "\\*/"));
        SUPPORTED_LANGUAGES.put("c", new Language("c", new String[]{".c", ".h"}, "//", "/\\*", "\\*/"));
    }

    public static void main(String[] args) {

        // 传入文件夹路径

        // "D:\\桌面\\code\\bit"
        // "D:\桌面\code\bit"
        // "D:\桌面\code\VS2022"
        // "D:\桌面\code\javacode"
        // "D:\桌面\code\cli"
        // "D:\桌面\code\pycharm"
        String directoryPath = "D:\\桌面\\code";
        File directory = new File(directoryPath);

        if (!directory.exists() || !directory.isDirectory()) {
            System.out.println("Invalid directory path.");
            return;
        }

        int totalLines = countCodeLines(directory);
        System.out.println("Total code lines: " + totalLines);
    }

    public static int countCodeLines(File directory) {
        int totalLines = 0;

        // 遍历文件夹中的所有文件
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    // 递归处理子文件夹
                    totalLines += countCodeLines(file);
                } else {
                    // 检查文件是否属于支持的语言
                    for (Language language : SUPPORTED_LANGUAGES.values()) {
                        for (String ext : language.extensions) {
                            if (file.getName().endsWith(ext)) {
                                totalLines += countLinesInFile(file, language);
                                break;
                            }
                        }
                    }
                }
            }
        }

        return totalLines;
    }

    public static int countLinesInFile(File file, Language language) {
        int lineCount = 0;
        boolean inBlockComment = false;
        Pattern singleLineCommentPattern = language.singleLineComment != null ? Pattern.compile("^\\s*" + language.singleLineComment + ".*$") : null;
        Pattern blockCommentStartPattern = language.blockCommentStart != null ? Pattern.compile(language.blockCommentStart) : null;
        Pattern blockCommentEndPattern = language.blockCommentEnd != null ? Pattern.compile(language.blockCommentEnd) : null;

        try (java.util.Scanner scanner = new java.util.Scanner(file)) {
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine().trim();

                // 检查是否进入块注释
                if (blockCommentStartPattern != null && line.contains(blockCommentStartPattern.toString())) {
                    inBlockComment = true;
                }

                // 跳过块注释
                if (!inBlockComment && (singleLineCommentPattern == null || !singleLineCommentPattern.matcher(line).matches())) {
                    lineCount++;
                }

                // 检查是否退出块注释
                if (blockCommentEndPattern != null && line.contains(blockCommentEndPattern.toString())) {
                    inBlockComment = false;
                }
            }
        } catch (Exception e) {
            System.out.println("Error reading file: " + file.getAbsolutePath());
            e.printStackTrace();
        }

        return lineCount;
    }

    // 定义语言类，存储语言的文件扩展名和注释规则
    private static class Language {
        String name;
        String[] extensions;
        String singleLineComment;
        String blockCommentStart;
        String blockCommentEnd;

        Language(String name, String[] extensions, String singleLineComment, String blockCommentStart, String blockCommentEnd) {
            this.name = name;
            this.extensions = extensions;
            this.singleLineComment = singleLineComment;
            this.blockCommentStart = blockCommentStart;
            this.blockCommentEnd = blockCommentEnd;
        }
    }
}